HTTP Request Smuggling vulnerability scanner.
Based on the work of PortSwigger and James Kettle (HTTP/1.1 Must Die, 2025).
| Type | Flag | Mechanism |
|---|---|---|
| CL.TE | --clte |
Frontend uses Content-Length, backend uses Transfer-Encoding |
| TE.CL | --tecl |
Frontend uses Transfer-Encoding, backend uses Content-Length |
| CL.0 | --CL0 |
Frontend uses Content-Length, backend ignores body |
| 0.CL | --_0CL |
Frontend ignores Content-Length, backend reads it |
| Expect | --expect |
Frontend drops body on Expect: 100-continue (CVE-2025-32094) |
| TE.0 | --te0 |
Frontend processes TE, backend ignores body entirely |
| Type | Flag | Mechanism |
|---|---|---|
| H2.CL | --h2cl |
Content-Length: 0 with body in DATA frame |
| H2.TE | --h2te |
Transfer-Encoding: chunked passed through downgrade (forbidden by spec) |
| H2.CRLF | --h2crlf |
\r\n in header value injects TE after downgrade |
| H2.Split | --h2split |
\r\n\r\n in header value splits request in two after downgrade |
| H2.Tunnel | --h2tunnel |
CRLF in header names, works without connection pooling |
HTTP/2 detections use absorption technique (smuggled request stays open with X-Ignore: X, no \r\n\r\n). Output includes Burp Repeater instructions.
Each HTTP/1.1 detection iterates over multiple header obfuscation variants (TE, CL, or Expect header mutations). By default 11 TE and 9 CL mutations are tested. Use --exhaustive for the extended set (37 TE, 21 CL) which adds defparam-style mutations.
TRACE method is also checked.
Full scans with all flags are slow. Focus on targets and endpoints most likely to be vulnerable.
- Sites behind CDNs/reverse proxies (Cloudflare, Akamai, AWS ALB, Fastly, Netlify) — the h2→h1 downgrade and connection pooling create the desync conditions
- Sites with mixed infrastructure — different proxy and backend technologies (nginx frontend + Apache/IIS/Gunicorn backend)
- Legacy or custom proxy setups — non-standard configurations are more likely to have parsing disagreements
- Bug bounty programs that explicitly include HTTP smuggling in scope
- Static file endpoints (
/images/,/resources/,/favicon.ico,.svg,.js) — backends often respond without reading the body (early response) → CL.0, TE.0 - Redirect endpoints (
/resources→/resources/) — server-level redirects often skip body reading - Error-triggering paths (reserved filenames like
/conon IIS) — backends respond immediately with errors - Login/logout endpoints — often have different backend routing
- API endpoints — may use different proxy rules than the main site
# 1. Quick H2 scan (fast, high impact)
python httpsmug.py -u target.com --all-h2
# 2. CL.TE / TE.CL with default mutations
python httpsmug.py -u target.com --clte --tecl
# 3. CL.0 on static endpoints (needs --spam for timing)
python httpsmug.py -u target.com/resources/images/blog.svg --CL0 --spam 30
# 4. Full scan with everything (slow, thorough)
python httpsmug.py -u target.com --all --exhaustive --chunk-ext --all-methods --spam 10pip install requests tqdm h2# All detections
python httpsmug.py -u example.com --all
# Specific detection
python httpsmug.py -u example.com --clte
python httpsmug.py -u example.com --expect
python httpsmug.py -u example.com --te0
# HTTP/2 detections
python httpsmug.py -u example.com --h2cl
python httpsmug.py -u example.com --h2te
python httpsmug.py -u example.com --h2crlf
python httpsmug.py -u example.com --h2split
python httpsmug.py -u example.com --h2tunnel
# With endpoint (required for CL.0 and 0.CL)
python httpsmug.py -u example.com/resources/images/blog.svg --CL0
# Batch scan from file
python httpsmug.py -l hosts.txt --allSome vulnerabilities (0.CL, CL.0) require multiple attempts due to backend connection pooling timing.
# Repeat each test 50 times
python httpsmug.py -u target.com --_0CL --spam 50
python httpsmug.py -u target.com --all --spam 30Test against PortSwigger labs or Docker test labs.
# List available lab types
python httpsmug.py --testlab list
# Validate against a PortSwigger lab
python httpsmug.py --testlab clte -u https://LABID.web-security-academy.net
# Validate against Docker lab (plain HTTP)
python httpsmug.py --testlab te0 --http --port 9004 -u localhost# Extended TE/CL header mutation set (37 TE + 21 CL variations)
python httpsmug.py -u target.com --all --exhaustive
# Chunk extension variations (exotic terminal chunks: 0;ext, 0 , 00, etc.)
python httpsmug.py -u target.com --all --chunk-ext
# Both
python httpsmug.py -u target.com --all --exhaustive --chunk-ext-u, --url Target host (with optional /endpoint)
-l, --list File with hosts to scan (one per line)
-A, --user-agent Custom User-Agent
--method HTTP method (default: POST)
--all-methods Test with all HTTP methods (POST, GET, OPTIONS, PUT, DELETE, PATCH)
--silent Silent mode (only show findings and status)
--http Use plain HTTP instead of HTTPS
--port N Custom port (default: 443 HTTPS, 80 HTTP)
--spam N Repeat each test N times per variation
--header 'N: V' Add custom header to all requests (repeatable)
--exhaustive Extended TE/CL header mutation set
--chunk-ext Chunk extension variations on terminal chunks
--testlab TYPE Lab validation mode
--h2cl Detect H2.CL (HTTP/2 Content-Length smuggling)
--h2te Detect H2.TE (HTTP/2 Transfer-Encoding smuggling)
--h2crlf Detect H2 CRLF injection
--h2split Detect H2 request splitting
--h2tunnel Detect H2 request tunnelling (CRLF in header names)
--all-h2 Run all HTTP/2 detections
--all Run all detections (HTTP/1.1 + HTTP/2)Reproducible test environments in tests/.
cd tests/
docker compose up -d --build
python run_tests.py # run all tests
python run_tests.py clte te0 # run specific tests
docker compose down| Lab | Port | Proxy mode | Backend mode |
|---|---|---|---|
| CL.TE | 9001 | cl | te |
| TE.CL | 9002 | te | cl |
| Expect | 9003 | expect | cl |
| TE.0 | 9004 | te_dechunk | none |
| Chunk-ext | 9005 | cl | te_strict |
Results saved to logs/httpsmug_YYYY-MM-DD.log. By default all tests are logged. In --silent mode only findings and status are recorded.
This tool is intended for authorized security testing only. Unauthorized use on systems without permission is illegal.